package com.example.demo.searcher;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicLong;

public class Parser {
    //先指定一个加载文档的路径
    private static final String INPUT_PATH = "E:/javaEE/doc_searcher_index/jdk-8u371-docs-all/docs/api";

    //创建一个Index实例
    private Index index = new Index();

    private AtomicLong t1 = new AtomicLong(0);
    private AtomicLong t2 = new AtomicLong(0);

    //单线程制作索引
    public void run(){
        long beg = System.currentTimeMillis();
        System.out.println("索引制作开始！");
        //入口
        //保存路径
        ArrayList<File> fileList = new ArrayList<>();
        long endEnumFile = System.currentTimeMillis();
        System.out.println("枚举文件完毕！消耗时间：" + (endEnumFile - beg) + " ms");
        enumFile(INPUT_PATH, fileList);
//        System.out.println(fileList);
//        System.out.println(fileList.size());
        for (File f : fileList){
            //解析html文件
            System.out.println("开始解析：" + f.getAbsolutePath());
            parseHTML(f);
        }
        long endFor = System.currentTimeMillis();
        System.out.println("遍历文件完毕！消耗时间：" + (endFor - beg) + " ms");
        index.save();
        long end = System.currentTimeMillis();
        System.out.println("索引制作完毕！消耗时间：" + (end - beg) + " ms");
    }

    //多线程制作索引
    public void runByThread() {
        long beg = System.currentTimeMillis();
        System.out.println("索引制作开始！");

        ArrayList<File> files = new ArrayList<>();
        enumFile(INPUT_PATH, files);
        CountDownLatch latch = new CountDownLatch(files.size());
        ExecutorService executorService = Executors.newFixedThreadPool(8);
        for (File f : files){
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("解析 " + f.getAbsolutePath());
                    parseHTML(f);
                    latch.countDown();
                }
            });
        }
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        executorService.shutdown();

        index.save();

        long end = System.currentTimeMillis();
        System.out.println("索引制作完毕！消耗时间：" + (end - beg) + " ms");
        System.out.println("t1: " + t1 + ", t2: "+ t2);
    }

    private void parseHTML(File f) {
        String title = parseTitle(f);
        String url = parseUrl(f);
        long beg = System.nanoTime();
        String content = parseContentByRegex(f);
        long mid = System.nanoTime();
        //TODO 把解析出来的这些信息加入到索引中
        index.addDoc(title, url, content);
        long end = System.nanoTime();
        t1.addAndGet(mid - beg);
        t2.addAndGet(end - mid);
    }

    public String parseContent(File f) {
        //手动设置缓冲区
        try(BufferedReader bufferedReader = new BufferedReader(new FileReader(f), 1024*1024)) {
            //是否进行拷贝
            boolean isCopy = true;
            //结果
            StringBuilder content = new StringBuilder();
            while (true){
                int ret = bufferedReader.read();
                if(ret == -1){
                    //文件读完了
                    break;
                }
                char c = (char)ret;
                if(isCopy){
                    //开关打开，拷贝
                    if(c == '<'){
                        isCopy = false;
                        continue;
                    }
                    //把换行替换成空格
                    if(c == '\n' || c == '\r'){
                        c = ' ';
                    }
                    content.append(c);
                }else{
                    //开关关闭，直到遇到>
                    if(c == '>'){
                        isCopy =true;
                    }
                }
            }
//            fileReader.close();
            return content.toString();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

    private String readFile(File f) {
        StringBuilder content = new StringBuilder();
        try (BufferedReader bufferedReader = new BufferedReader(new FileReader(f))) {
            while (true) {
                String line = bufferedReader.readLine();
                if (line == null) {
                    break;
                }
                content.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return content.toString();
    }

    public String parseContentByRegex(File f) {
        // 1. 先把整个文件内容都读取出来
        String content = readFile(f);
        // 2. 使用正则替换掉 <script> 标签
        content = content.replaceAll("<script.*?>(.*?)</script>", " ");
        // 3. 使用正则替换掉其他标签
        content = content.replaceAll("<.*?>", " ");
        // 4. 多个空格合并成一个
        content = content.replaceAll("\\s+", " ");
        return content;
    }

    private String parseUrl(File f) {
        String part1 = "https:\\\\docs.oracle.com\\javase\\8\\docs\\api";
        String part2 = f.getAbsolutePath().substring(INPUT_PATH.length());
        return part1 + part2;
    }

    private String parseTitle(File f) {
        String name = f.getName();
        return name.substring(0, name.length() - ".html".length());
    }

    /**
     *
     * @param inputPath 从哪个目录开始进行递归遍历
     * @param fileList 递归得到的结果
     */
    private void enumFile(String inputPath, ArrayList<File> fileList) {
        File rootPath = new File(inputPath);
        //rootPath当前目录下包含的文件（一层）
        File[] files = rootPath.listFiles();
        System.out.println(Arrays.toString(files));
        for (File f : files){
            //根据类型决定是否要递归
            if(f.isDirectory()){
                enumFile(f.getAbsolutePath(), fileList);
            }else{
                //判断是否为.html结尾
                if(f.getAbsolutePath().endsWith(".html"))
                fileList.add(f);
            }
        }
    }

    public static void main(String[] args) {
        Parser parser = new Parser();
        parser.runByThread();
    }
}
